/**
 * 前端功能测试运行器
 * 使用Puppeteer测试UI交互和状态管理
 */

const puppeteer = require('puppeteer');
const path = require('path');
const chalk = require('chalk');
const config = require('../../config/test-config');
const TestUtils = require('../../utils/test-utils');

class FrontendTestRunner {
  constructor() {
    this.testUtils = new TestUtils(config);
    this.browser = null;
    this.page = null;
  }

  /**
   * 运行所有前端测试
   */
  async runAllTests() {
    console.log(chalk.bold.blue('开始执行前端功能测试...'));
    console.log(chalk.gray(`测试URL: ${config.frontend.baseUrl}`));
    console.log(chalk.gray('='.repeat(60)));

    try {
      // 启动浏览器
      await this.setupBrowser();
      
      // 1. 应用初始化测试
      await this.testApplicationInitialization();
      
      // 2. 用户界面测试
      await this.testUserInterface();
      
      // 3. 任务管理界面测试
      await this.testTaskManagementUI();
      
      // 4. 清单管理界面测试
      await this.testListManagementUI();
      
      // 5. 番茄钟界面测试
      await this.testPomodoroUI();
      
      // 6. 白噪音界面测试
      await this.testWhiteNoiseUI();
      
      // 7. 统计界面测试
      await this.testStatisticsUI();
      
      // 8. 日历视图测试
      await this.testCalendarUI();
      
      // 9. 设置界面测试
      await this.testSettingsUI();
      
      // 10. 响应式设计测试
      await this.testResponsiveDesign();
      
    } catch (error) {
      console.error(chalk.red(`前端测试执行失败: ${error.message}`));
    } finally {
      // 关闭浏览器
      await this.teardownBrowser();
      
      // 打印测试摘要
      this.testUtils.printTestSummary();
      
      // 保存测试结果
      const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
      await this.testUtils.saveTestResults(`frontend-test-results-${timestamp}.json`);
    }
  }

  /**
   * 设置浏览器环境
   */
  async setupBrowser() {
    this.browser = await puppeteer.launch({
      headless: config.browser.headless,
      defaultViewport: {
        width: config.browser.viewport.width,
        height: config.browser.viewport.height
      },
      args: ['--no-sandbox', '--disable-setuid-sandbox']
    });
    
    this.page = await this.browser.newPage();
    
    // 设置页面事件监听
    this.page.on('console', msg => {
      if (msg.type() === 'error') {
        console.log(chalk.red(`浏览器控制台错误: ${msg.text()}`));
      }
    });
    
    this.page.on('pageerror', error => {
      console.log(chalk.red(`页面错误: ${error.message}`));
    });
  }

  /**
   * 清理浏览器环境
   */
  async teardownBrowser() {
    if (this.browser) {
      await this.browser.close();
    }
  }

  /**
   * 测试应用初始化
   */
  async testApplicationInitialization() {
    console.log(chalk.cyan('\n🚀 测试应用初始化...'));
    
    await this.testPageLoad();
    await this.testInitialState();
  }

  async testPageLoad() {
    const startTime = Date.now();
    try {
      await this.page.goto(config.frontend.baseUrl, { 
        waitUntil: 'networkidle2',
        timeout: 30000
      });
      
      // 检查页面标题
      const title = await this.page.title();
      if (!title || title.trim() === '') {
        throw new Error('页面标题为空');
      }
      
      this.testUtils.recordTestResult(
        '页面加载',
        'APPLICATION_INIT',
        'passed',
        Date.now() - startTime,
        null,
        '测试应用页面加载功能'
      );
    } catch (error) {
      this.testUtils.recordTestResult(
        '页面加载',
        'APPLICATION_INIT',
        'failed',
        Date.now() - startTime,
        error.message,
        '测试应用页面加载功能'
      );
    }
  }

  async testInitialState() {
    const startTime = Date.now();
    try {
      // 等待Vue应用初始化
      await this.page.waitForSelector('[data-testid="app-container"], .app, #app', { timeout: 10000 });
      
      // 检查主要组件是否存在
      const hasNavigation = await this.page.$('.navigation, .nav, [data-testid="navigation"]');
      const hasMainContent = await this.page.$('.main-content, .content, [data-testid="main-content"]');
      
      if (!hasNavigation && !hasMainContent) {
        throw new Error('主要UI组件未正确加载');
      }
      
      this.testUtils.recordTestResult(
        '初始状态',
        'APPLICATION_INIT',
        'passed',
        Date.now() - startTime,
        null,
        '测试应用初始状态'
      );
    } catch (error) {
      this.testUtils.recordTestResult(
        '初始状态',
        'APPLICATION_INIT',
        'failed',
        Date.now() - startTime,
        error.message,
        '测试应用初始状态'
      );
    }
  }

  /**
   * 测试用户界面
   */
  async testUserInterface() {
    console.log(chalk.cyan('\n👤 测试用户界面...'));
    
    await this.testNavigationMenu();
    await this.testThemeToggle();
  }

  async testNavigationMenu() {
    const startTime = Date.now();
    try {
      // 查找导航菜单
      const navSelectors = [
        '.navigation-menu',
        '.nav-menu', 
        '.sidebar',
        '[data-testid="navigation-menu"]',
        '.menu'
      ];
      
      let navElement = null;
      for (const selector of navSelectors) {
        navElement = await this.page.$(selector);
        if (navElement) break;
      }
      
      if (!navElement) {
        throw new Error('未找到导航菜单');
      }
      
      // 测试菜单项点击
      const menuItems = await this.page.$$(`${navSelectors.find(s => navElement)} a, ${navSelectors.find(s => navElement)} button`);
      
      if (menuItems.length > 0) {
        await menuItems[0].click();
        await this.page.waitForTimeout(500);
      }
      
      this.testUtils.recordTestResult(
        '导航菜单',
        'USER_INTERFACE',
        'passed',
        Date.now() - startTime,
        null,
        '测试导航菜单功能'
      );
    } catch (error) {
      this.testUtils.recordTestResult(
        '导航菜单',
        'USER_INTERFACE',
        'failed',
        Date.now() - startTime,
        error.message,
        '测试导航菜单功能'
      );
    }
  }

  async testThemeToggle() {
    const startTime = Date.now();
    try {
      // 查找主题切换按钮
      const themeSelectors = [
        '.theme-toggle',
        '.dark-mode-toggle',
        '[data-testid="theme-toggle"]',
        'button[title*="主题"]',
        'button[title*="theme"]'
      ];
      
      let themeButton = null;
      for (const selector of themeSelectors) {
        themeButton = await this.page.$(selector);
        if (themeButton) break;
      }
      
      if (themeButton) {
        // 获取当前主题
        const initialTheme = await this.page.evaluate(() => {
          return document.documentElement.getAttribute('data-theme') || 
                 document.body.className.includes('dark') ? 'dark' : 'light';
        });
        
        // 点击主题切换
        await themeButton.click();
        await this.page.waitForTimeout(500);
        
        // 检查主题是否改变
        const newTheme = await this.page.evaluate(() => {
          return document.documentElement.getAttribute('data-theme') || 
                 document.body.className.includes('dark') ? 'dark' : 'light';
        });
        
        if (initialTheme === newTheme) {
          throw new Error('主题切换未生效');
        }
      }
      
      this.testUtils.recordTestResult(
        '主题切换',
        'USER_INTERFACE',
        'passed',
        Date.now() - startTime,
        null,
        '测试主题切换功能'
      );
    } catch (error) {
      this.testUtils.recordTestResult(
        '主题切换',
        'USER_INTERFACE',
        'failed',
        Date.now() - startTime,
        error.message,
        '测试主题切换功能'
      );
    }
  }

  /**
   * 测试任务管理界面
   */
  async testTaskManagementUI() {
    console.log(chalk.cyan('\n✅ 测试任务管理界面...'));
    
    await this.testTaskCreation();
    await this.testTaskList();
    await this.testTaskCompletion();
  }

  async testTaskCreation() {
    const startTime = Date.now();
    try {
      // 查找添加任务按钮
      const addButtonSelectors = [
        '.add-task-btn',
        '.new-task-btn',
        '[data-testid="add-task"]',
        'button[title*="添加"]',
        'button[title*="新建"]'
      ];
      
      let addButton = null;
      for (const selector of addButtonSelectors) {
        addButton = await this.page.$(selector);
        if (addButton) break;
      }
      
      if (!addButton) {
        throw new Error('未找到添加任务按钮');
      }
      
      // 点击添加按钮
      await addButton.click();
      await this.page.waitForTimeout(500);
      
      // 查找任务输入框
      const inputSelectors = [
        'input[placeholder*="任务"]',
        'input[placeholder*="task"]',
        '.task-input',
        '[data-testid="task-input"]'
      ];
      
      let taskInput = null;
      for (const selector of inputSelectors) {
        taskInput = await this.page.$(selector);
        if (taskInput) break;
      }
      
      if (taskInput) {
        // 输入任务内容
        await taskInput.type('测试任务 - ' + Date.now());
        
        // 提交任务
        await this.page.keyboard.press('Enter');
        await this.page.waitForTimeout(1000);
      }
      
      this.testUtils.recordTestResult(
        '创建任务',
        'TASK_MANAGEMENT_UI',
        'passed',
        Date.now() - startTime,
        null,
        '测试任务创建界面功能'
      );
    } catch (error) {
      this.testUtils.recordTestResult(
        '创建任务',
        'TASK_MANAGEMENT_UI',
        'failed',
        Date.now() - startTime,
        error.message,
        '测试任务创建界面功能'
      );
    }
  }

  async testTaskList() {
    const startTime = Date.now();
    try {
      // 查找任务列表
      const listSelectors = [
        '.task-list',
        '.todo-list',
        '[data-testid="task-list"]',
        '.tasks'
      ];
      
      let taskList = null;
      for (const selector of listSelectors) {
        taskList = await this.page.$(selector);
        if (taskList) break;
      }
      
      if (!taskList) {
        throw new Error('未找到任务列表');
      }
      
      // 检查任务项
      const taskItems = await this.page.$$('.task-item, .todo-item, [data-testid="task-item"]');
      
      this.testUtils.recordTestResult(
        '任务列表',
        'TASK_MANAGEMENT_UI',
        'passed',
        Date.now() - startTime,
        null,
        `测试任务列表显示功能 (找到${taskItems.length}个任务)`
      );
    } catch (error) {
      this.testUtils.recordTestResult(
        '任务列表',
        'TASK_MANAGEMENT_UI',
        'failed',
        Date.now() - startTime,
        error.message,
        '测试任务列表显示功能'
      );
    }
  }

  async testTaskCompletion() {
    const startTime = Date.now();
    try {
      // 查找第一个任务的完成按钮
      const checkboxSelectors = [
        '.task-checkbox',
        '.todo-checkbox',
        'input[type="checkbox"]',
        '[data-testid="task-checkbox"]'
      ];
      
      let checkbox = null;
      for (const selector of checkboxSelectors) {
        checkbox = await this.page.$(selector);
        if (checkbox) break;
      }
      
      if (checkbox) {
        // 点击完成任务
        await checkbox.click();
        await this.page.waitForTimeout(500);
      }
      
      this.testUtils.recordTestResult(
        '完成任务',
        'TASK_MANAGEMENT_UI',
        'passed',
        Date.now() - startTime,
        null,
        '测试任务完成界面功能'
      );
    } catch (error) {
      this.testUtils.recordTestResult(
        '完成任务',
        'TASK_MANAGEMENT_UI',
        'failed',
        Date.now() - startTime,
        error.message,
        '测试任务完成界面功能'
      );
    }
  }

  /**
   * 测试清单管理界面
   */
  async testListManagementUI() {
    console.log(chalk.cyan('\n📋 测试清单管理界面...'));
    
    await this.testListCreation();
    await this.testListSwitching();
  }

  async testListCreation() {
    const startTime = Date.now();
    try {
      // 查找添加清单按钮
      const addListSelectors = [
        '.add-list-btn',
        '.new-list-btn',
        '[data-testid="add-list"]',
        'button[title*="清单"]'
      ];
      
      let addListButton = null;
      for (const selector of addListSelectors) {
        addListButton = await this.page.$(selector);
        if (addListButton) break;
      }
      
      if (addListButton) {
        await addListButton.click();
        await this.page.waitForTimeout(500);
        
        // 查找清单名称输入框
        const listInputSelectors = [
          'input[placeholder*="清单"]',
          'input[placeholder*="list"]',
          '.list-input',
          '[data-testid="list-input"]'
        ];
        
        let listInput = null;
        for (const selector of listInputSelectors) {
          listInput = await this.page.$(selector);
          if (listInput) break;
        }
        
        if (listInput) {
          await listInput.type('测试清单 - ' + Date.now());
          await this.page.keyboard.press('Enter');
          await this.page.waitForTimeout(1000);
        }
      }
      
      this.testUtils.recordTestResult(
        '创建清单',
        'LIST_MANAGEMENT_UI',
        'passed',
        Date.now() - startTime,
        null,
        '测试清单创建界面功能'
      );
    } catch (error) {
      this.testUtils.recordTestResult(
        '创建清单',
        'LIST_MANAGEMENT_UI',
        'failed',
        Date.now() - startTime,
        error.message,
        '测试清单创建界面功能'
      );
    }
  }

  async testListSwitching() {
    const startTime = Date.now();
    try {
      // 查找清单列表
      const listItems = await this.page.$$('.list-item, .sidebar-item, [data-testid="list-item"]');
      
      if (listItems.length > 1) {
        // 点击第二个清单
        await listItems[1].click();
        await this.page.waitForTimeout(500);
      }
      
      this.testUtils.recordTestResult(
        '切换清单',
        'LIST_MANAGEMENT_UI',
        'passed',
        Date.now() - startTime,
        null,
        '测试清单切换界面功能'
      );
    } catch (error) {
      this.testUtils.recordTestResult(
        '切换清单',
        'LIST_MANAGEMENT_UI',
        'failed',
        Date.now() - startTime,
        error.message,
        '测试清单切换界面功能'
      );
    }
  }

  /**
   * 测试番茄钟界面
   */
  async testPomodoroUI() {
    console.log(chalk.cyan('\n🍅 测试番茄钟界面...'));
    
    await this.testPomodoroTimer();
  }

  async testPomodoroTimer() {
    const startTime = Date.now();
    try {
      // 查找番茄钟相关元素
      const pomodoroSelectors = [
        '.pomodoro',
        '.timer',
        '[data-testid="pomodoro"]',
        '.pomodoro-timer'
      ];
      
      let pomodoroElement = null;
      for (const selector of pomodoroSelectors) {
        pomodoroElement = await this.page.$(selector);
        if (pomodoroElement) break;
      }
      
      if (pomodoroElement) {
        // 查找开始按钮
        const startButton = await this.page.$('.start-btn, .play-btn, [data-testid="start-timer"]');
        if (startButton) {
          await startButton.click();
          await this.page.waitForTimeout(1000);
          
          // 查找暂停按钮
          const pauseButton = await this.page.$('.pause-btn, [data-testid="pause-timer"]');
          if (pauseButton) {
            await pauseButton.click();
            await this.page.waitForTimeout(500);
          }
        }
      }
      
      this.testUtils.recordTestResult(
        '番茄钟计时器',
        'POMODORO_UI',
        'passed',
        Date.now() - startTime,
        null,
        '测试番茄钟计时器界面功能'
      );
    } catch (error) {
      this.testUtils.recordTestResult(
        '番茄钟计时器',
        'POMODORO_UI',
        'failed',
        Date.now() - startTime,
        error.message,
        '测试番茄钟计时器界面功能'
      );
    }
  }

  /**
   * 测试白噪音界面
   */
  async testWhiteNoiseUI() {
    console.log(chalk.cyan('\n🎵 测试白噪音界面...'));
    
    await this.testWhiteNoisePlayer();
  }

  async testWhiteNoisePlayer() {
    const startTime = Date.now();
    try {
      // 查找白噪音相关元素
      const noiseSelectors = [
        '.white-noise',
        '.noise-player',
        '[data-testid="white-noise"]',
        '.ambient-sound'
      ];
      
      let noiseElement = null;
      for (const selector of noiseSelectors) {
        noiseElement = await this.page.$(selector);
        if (noiseElement) break;
      }
      
      if (noiseElement) {
        // 查找播放按钮
        const playButton = await this.page.$('.noise-play-btn, .play-noise, [data-testid="play-noise"]');
        if (playButton) {
          await playButton.click();
          await this.page.waitForTimeout(1000);
          
          // 查找音量控制
          const volumeSlider = await this.page.$('input[type="range"], .volume-slider');
          if (volumeSlider) {
            await volumeSlider.click();
          }
        }
      }
      
      this.testUtils.recordTestResult(
        '白噪音播放器',
        'WHITE_NOISE_UI',
        'passed',
        Date.now() - startTime,
        null,
        '测试白噪音播放器界面功能'
      );
    } catch (error) {
      this.testUtils.recordTestResult(
        '白噪音播放器',
        'WHITE_NOISE_UI',
        'failed',
        Date.now() - startTime,
        error.message,
        '测试白噪音播放器界面功能'
      );
    }
  }

  /**
   * 测试统计界面
   */
  async testStatisticsUI() {
    console.log(chalk.cyan('\n📊 测试统计界面...'));
    
    await this.testStatisticsDisplay();
  }

  async testStatisticsDisplay() {
    const startTime = Date.now();
    try {
      // 查找统计相关元素
      const statsSelectors = [
        '.statistics',
        '.stats',
        '[data-testid="statistics"]',
        '.analytics'
      ];
      
      let statsElement = null;
      for (const selector of statsSelectors) {
        statsElement = await this.page.$(selector);
        if (statsElement) break;
      }
      
      if (statsElement) {
        // 检查图表元素
        const charts = await this.page.$$('.chart, canvas, svg');
        
        this.testUtils.recordTestResult(
          '统计数据显示',
          'STATISTICS_UI',
          'passed',
          Date.now() - startTime,
          null,
          `测试统计数据显示界面功能 (找到${charts.length}个图表)`
        );
      } else {
        throw new Error('未找到统计界面元素');
      }
    } catch (error) {
      this.testUtils.recordTestResult(
        '统计数据显示',
        'STATISTICS_UI',
        'failed',
        Date.now() - startTime,
        error.message,
        '测试统计数据显示界面功能'
      );
    }
  }

  /**
   * 测试日历界面
   */
  async testCalendarUI() {
    console.log(chalk.cyan('\n📅 测试日历界面...'));
    
    await this.testCalendarView();
  }

  async testCalendarView() {
    const startTime = Date.now();
    try {
      // 查找日历相关元素
      const calendarSelectors = [
        '.calendar',
        '.calendar-view',
        '[data-testid="calendar"]',
        '.date-picker'
      ];
      
      let calendarElement = null;
      for (const selector of calendarSelectors) {
        calendarElement = await this.page.$(selector);
        if (calendarElement) break;
      }
      
      if (calendarElement) {
        // 查找日期单元格
        const dateCells = await this.page.$$('.calendar-day, .date-cell, .day');
        
        if (dateCells.length > 0) {
          // 点击一个日期
          await dateCells[Math.floor(dateCells.length / 2)].click();
          await this.page.waitForTimeout(500);
        }
        
        this.testUtils.recordTestResult(
          '日历视图',
          'CALENDAR_UI',
          'passed',
          Date.now() - startTime,
          null,
          `测试日历视图界面功能 (找到${dateCells.length}个日期单元格)`
        );
      } else {
        throw new Error('未找到日历界面元素');
      }
    } catch (error) {
      this.testUtils.recordTestResult(
        '日历视图',
        'CALENDAR_UI',
        'failed',
        Date.now() - startTime,
        error.message,
        '测试日历视图界面功能'
      );
    }
  }

  /**
   * 测试设置界面
   */
  async testSettingsUI() {
    console.log(chalk.cyan('\n⚙️ 测试设置界面...'));
    
    await this.testSettingsPanel();
  }

  async testSettingsPanel() {
    const startTime = Date.now();
    try {
      // 查找设置按钮
      const settingsSelectors = [
        '.settings-btn',
        '.config-btn',
        '[data-testid="settings"]',
        'button[title*="设置"]'
      ];
      
      let settingsButton = null;
      for (const selector of settingsSelectors) {
        settingsButton = await this.page.$(selector);
        if (settingsButton) break;
      }
      
      if (settingsButton) {
        await settingsButton.click();
        await this.page.waitForTimeout(1000);
        
        // 查找设置面板
        const settingsPanel = await this.page.$('.settings-panel, .config-panel, [data-testid="settings-panel"]');
        
        if (settingsPanel) {
          // 查找设置项
          const settingsItems = await this.page.$$('.setting-item, .config-item, input, select');
          
          this.testUtils.recordTestResult(
            '设置面板',
            'SETTINGS_UI',
            'passed',
            Date.now() - startTime,
            null,
            `测试设置面板界面功能 (找到${settingsItems.length}个设置项)`
          );
        } else {
          throw new Error('设置面板未正确打开');
        }
      } else {
        throw new Error('未找到设置按钮');
      }
    } catch (error) {
      this.testUtils.recordTestResult(
        '设置面板',
        'SETTINGS_UI',
        'failed',
        Date.now() - startTime,
        error.message,
        '测试设置面板界面功能'
      );
    }
  }

  /**
   * 测试响应式设计
   */
  async testResponsiveDesign() {
    console.log(chalk.cyan('\n📱 测试响应式设计...'));
    
    await this.testMobileView();
    await this.testTabletView();
  }

  async testMobileView() {
    const startTime = Date.now();
    try {
      // 设置移动端视口
      await this.page.setViewport({ width: 375, height: 667 });
      await this.page.waitForTimeout(1000);
      
      // 检查移动端布局
      const isMobileLayout = await this.page.evaluate(() => {
        const width = window.innerWidth;
        return width <= 768;
      });
      
      if (!isMobileLayout) {
        throw new Error('移动端布局未正确应用');
      }
      
      this.testUtils.recordTestResult(
        '移动端视图',
        'RESPONSIVE_DESIGN',
        'passed',
        Date.now() - startTime,
        null,
        '测试移动端响应式设计'
      );
    } catch (error) {
      this.testUtils.recordTestResult(
        '移动端视图',
        'RESPONSIVE_DESIGN',
        'failed',
        Date.now() - startTime,
        error.message,
        '测试移动端响应式设计'
      );
    }
  }

  async testTabletView() {
    const startTime = Date.now();
    try {
      // 设置平板端视口
      await this.page.setViewport({ width: 768, height: 1024 });
      await this.page.waitForTimeout(1000);
      
      // 检查平板端布局
      const isTabletLayout = await this.page.evaluate(() => {
        const width = window.innerWidth;
        return width >= 768 && width <= 1024;
      });
      
      if (!isTabletLayout) {
        throw new Error('平板端布局未正确应用');
      }
      
      this.testUtils.recordTestResult(
        '平板端视图',
        'RESPONSIVE_DESIGN',
        'passed',
        Date.now() - startTime,
        null,
        '测试平板端响应式设计'
      );
    } catch (error) {
      this.testUtils.recordTestResult(
        '平板端视图',
        'RESPONSIVE_DESIGN',
        'failed',
        Date.now() - startTime,
        error.message,
        '测试平板端响应式设计'
      );
    }
  }
}

// 如果直接运行此文件，则执行测试
if (require.main === module) {
  const runner = new FrontendTestRunner();
  runner.runAllTests().catch(console.error);
}

module.exports = FrontendTestRunner;